/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package lintulaskenta.utils;


import java.io.StringReader;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Attr;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;

import lintulaskenta.utils.Document.Node;

/**
 * Parses a Document container out of XML
 * @see Document
 */
public class XMLReader {

	public Document parse(String xml) {
		org.w3c.dom.Node domRootNode = getRoot(xml);
		if (domRootNode == null) return null;

		Document d = new Document(domRootNode.getNodeName());
		Node documentRootNode = d.getRootNode();
		parse(domRootNode, documentRootNode);
		return d;
	}

	private void parse(org.w3c.dom.Node domNode, Node documentNode) {
		setAttributes(domNode, documentNode);
		NodeList childList = domNode.getChildNodes();
		for (int i=0; i<childList.getLength(); i++) {
			org.w3c.dom.Node domChildNode = childList.item(i);
			if (domChildNode.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE) {
				Node documentChildNode = documentNode.addChildNode(domChildNode.getNodeName());
				parse(domChildNode, documentChildNode);
			}
			else if (domChildNode.getNodeType() == org.w3c.dom.Node.TEXT_NODE) {
				String contents = domChildNode.getTextContent().trim();
				if (contents.length() > 0) {
					documentNode.setContents(contents);
				}
			}
			else if (domChildNode.getNodeType() == org.w3c.dom.Node.CDATA_SECTION_NODE) {
				documentNode.setCDATA(domChildNode.getTextContent());
			}
		}
	}

	private void setAttributes(org.w3c.dom.Node domElement, Node node) {
		NamedNodeMap attributes = domElement.getAttributes();
		for (int i = 0; i<attributes.getLength(); i++) {
			Attr attribute = (Attr) attributes.item(i);
			node.addAttribute(attribute.getName(), attribute.getValue());
		}
	}

	private Element getRoot(String xml) {
		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
		DocumentBuilder db;
		try {
			db = dbf.newDocumentBuilder();
		} catch (ParserConfigurationException e) {
			e.printStackTrace();
			return null;
		}
		InputSource is = new InputSource();
		is.setCharacterStream(new StringReader(xml));
		org.w3c.dom.Document doc;
		try {
			doc = db.parse(is);
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
		Element root = doc.getDocumentElement();
		return root;
	}

}